﻿(function () {
    "use strict";

    // Ajax related functions. The AJAX error handling was loosely based upon:
    // http://www.novogeek.com/post/2009/12/13/Handling-AJAX-exceptions-of-ASPNET-using-jQuery.aspx

    function Ajax(maxAttempts, retryStatusCodes) {

        var errFlag = false;

        function init() {
            $.ajaxSetup({
                error: defaultErrorHandler
            });
        }

        function parseAjaxError(jqXHR, textStatus) {

            var errMsg = '';

            if (jqXHR.status === 403) {
                if (jqXHR.responseText === "You do not have the correct subscription required to view the requested content.") {
                    // Forbidden - logged in, but content is not accessible
                    errMsg = $('#error_msg_403').html();
                } else {
                    // Unauthorized - redirect the user to the logon page
                    // TODO: this should not be handled here
                    window.location.href = $('#logon').attr('href');
                }
            } else if (jqXHR.status === 404) {
                errMsg = $('#error_msg_404').html();
            } else if (jqXHR.status === 500) {
                errMsg = $('#error_msg_500').html();
            } else if (jqXHR.status === 504) {
                errMsg = $('#error_msg_504').html();
            } else {
                errMsg = $('#error_msg_unknown').html();
                errMsg = errMsg + " jqXHR.status=" + jqXHR.status + " textStatus=" + textStatus;
            }

            return errMsg;
        }

        function defaultErrorHandler(jqXHR, textStatus) {
            if (textStatus === "error" && jqXHR.status === 0) {
                // Do nothing. Because, this happens when the user refreshes the page, during an ajax request (In non-IE (non-stone age) browsers).
            } else if (textStatus === "abort") {
                // Do nothing. Ajax request has been aborted.
            } else {
                //displayError(parseAjaxError(jqXHR, textStatus));
                ZEUS.DEBUG.error(parseAjaxError(jqXHR, textStatus));
            }
        }

        function beforeSendHandler() {
            var settings = this.dashboard;

            // Only trigger the beforeSend event to clients on the first attempt
            if (settings.sendAttempt === 1 && settings.beforeSend) {
                settings.beforeSend.apply(this, arguments);
            }
            settings.suppressComplete = false;
        }

        function sendErrorHandler(jqXHR) {
            var settings = this.dashboard;

            if ($.inArray(jqXHR.status, retryStatusCodes) !== -1
                            && settings.sendAttempt < maxAttempts) {
                settings.suppressComplete = true;
                settings.sendAttempt++;
                $.ajax(this).done(doneHandler);
            }
            else {
                if (settings.error) {
                    settings.error.apply(this, arguments);
                } else if (this.global) {
                    if ($.ajaxSettings.error) {
                        $.ajaxSettings.error.apply(this, arguments);
                    }
                }
                settings.deferred.rejectWith(this, arguments);
            }
        }

        function sendCompleteHandler() {
            var settings = this.dashboard;

            if (!settings.suppressComplete) {
                if (settings.complete) {
                    settings.complete.apply(this, arguments);
                }
            }
        }

        function send(settings) {
            var deferred = new $.Deferred();

            // The ajax settings object is maintained between calls
            // and is available in event callbacks through 'this'.
            // It makes it idea to store variables related to our
            // modified functionality
            settings.dashboard = {
                sendAttempt: 1,
                error: settings.error,
                complete: settings.complete,
                beforeSend: settings.beforeSend,
                deferred: deferred
            };

            // Overwrite jQuery ajax handlers with dashboard auto-retry handlers
            settings.complete = sendCompleteHandler;
            settings.error = sendErrorHandler;
            settings.beforeSend = beforeSendHandler;

            $.ajax(settings).done(doneHandler);

            return deferred.promise();
        }

        function doneHandler(data) {
            this.dashboard.deferred.resolveWith(this, [data]);
        }

        function hasErrFlag() {
            return errFlag;
        }

        function setErrFlag(bFlag) {
            errFlag = bFlag;
        }

        return {
            init: init,
            defaultErrorHandler: defaultErrorHandler,
            //displayError: displayError,
            parseAjaxError: parseAjaxError,
            send: send,
            hasErrFlag: hasErrFlag,
            setErrFlag: setErrFlag
        };
    }

    // Namespace w/global object
    $.ZEUS = $.ZEUS || {};

    // Internet Explorer seems to sometimes have connection timeouts which causes a failure for the first
    // ajax request after the timeout. This usually causes a 12002 status code.
    // Also, Internet Explorer is inflicted with a bug which causes a post body to be missing after connection
    // timeouts. The server application detects these missing bodies and returns a 408 status code.
    // Therefore, it is sensible to automatically retry all posts, as our actions are idempotent (can be executed more
    // than once without further side effects). If these changes, then we must suppress auto-retry for these cases.
    $.ZEUS.ajax = new Ajax(3, [408, 12002]);

    $.ZEUS.testAccessor = $.ZEUS.testAccessor || {};
    $.ZEUS.testAccessor.Ajax = Ajax;

    $.ZEUS.ajax.init();

} ());
